/****************************************************************
 *This file is thread-one.c
 ****************************************************************/

#include "include.h"

//inner function declare
static void *pc_command_get_func(void *arg);
static void pc_command_process_func(const unsigned char *arg, unsigned int len, unsigned char *return_arg, unsigned int *return_len);

/****************************************************************
 *This function is thread1
 *	(1)create socket,listen port,process command
 ****************************************************************/
void *thread1(void *str)
{
	//inner variable
	pthread_t pth;
	int ret;

	int sockfd, new_fd;
	struct sockaddr_in my_addr;
	struct sockaddr_in their_addr;
	unsigned int sin_size;
	pthread_socket_message socket_one_client_message;

	str = str;
    ret = 0;
    ret = ret;

	//create pc command socket file descriptor
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		fprintf(stderr,"sockfd create error!\n");
		exit(1);
   	 }

	//bind port to pc command socket file descriptor
	bzero(&my_addr, sizeof(my_addr));
	my_addr.sin_family=AF_INET;
	my_addr.sin_port=htons(NET_COMMAND_PORT);
	my_addr.sin_addr.s_addr = INADDR_ANY;
	if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
	{
		fprintf(stderr,"sockfd bind error!\n");
		exit(1);
	}

	//listen PC_COMMAND_PORT port
	if (listen(sockfd, SOMAXCONN) == -1)
	{
		fprintf(stderr,"sockfd listen error!\n");
		exit(1);
	}

	//clear client net message
	bzero(&their_addr, sizeof(their_addr));

#ifdef	TST_CODE_SWITCH
	fprintf(stderr,"create socket ok\n");
#endif

	//task scheduler
	while(1)
	{
		//wait for client connect
		sin_size = sizeof(struct sockaddr_in);
		if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
		{
			fprintf(stderr,"sockfd accept error!\n");
			continue;
		}

		//fill client socket message
		socket_one_client_message.client_addr = their_addr.sin_addr;
		socket_one_client_message.client_port = their_addr.sin_port;
		socket_one_client_message.sockfd = new_fd;

#ifdef	TST_CODE_SWITCH
	fprintf(stderr,"client port is:%d\n", \
            socket_one_client_message.client_port);
#endif

		//creat pc_command_get_func thread
		ret = pthread_create(&pth, NULL, pc_command_get_func, (void *)(&socket_one_client_message));
	}

	return NULL;
}

/****************************************************************
 *This function is pc_command_get_func
 *	(1)read command from network and  process command
 ****************************************************************/
static void *pc_command_get_func(void *arg)
{
	pthread_socket_message client_message;
	unsigned char net_command_buf[NET_COMMAND_BUF_LEN];
	unsigned char net_command_buf_ack[NET_COMMAND_BUF_LEN];
	unsigned int  net_command_buf_len_ack;
	unsigned int client_addr;
	unsigned short client_port;
	int net_command_buf_len;

    client_port = 0;
    client_port = client_port;
    client_addr = 0;
    client_addr = client_addr;

	//I am free
	pthread_detach(pthread_self());

	//get client message
	client_message  = *((pthread_socket_message *)arg);

	//record client connect,IP address:inet_ntoa(client_message.client_addr)(%s), port:ntohs(client_message.client_port)(%d)
	client_addr = ntohl(client_message.client_addr.s_addr);
	client_port = ntohs(client_message.client_port);

#ifdef	TST_CODE_SWITCH
	fprintf(stderr,"pthread client_addr is:%d, client_port is:%d\n", client_addr, client_port);
#endif

	//init inner variable
	net_command_buf_len = 0;
	net_command_buf_len_ack = 0;
	bzero(net_command_buf, NET_COMMAND_BUF_LEN);
	bzero(net_command_buf_ack, NET_COMMAND_BUF_LEN);

	//read data from network
	net_command_buf_len = read(client_message.sockfd, net_command_buf, NET_COMMAND_BUF_LEN);
	while((net_command_buf_len > 0) || ((net_command_buf_len < 0) && (errno == EINTR)))
	{
		//process get command,data in net_command_buf,length in net_command_buf_len
		net_command_buf_ack[0] = (unsigned char)(client_message.sockfd >> 24);
		net_command_buf_ack[1] = (unsigned char)(client_message.sockfd >> 16);
		net_command_buf_ack[2] = (unsigned char)(client_message.sockfd >> 8);
		net_command_buf_ack[3] = (unsigned char)(client_message.sockfd >> 0);
		pc_command_process_func(net_command_buf, (unsigned int)net_command_buf_len, net_command_buf_ack, &net_command_buf_len_ack);

		//write comamnd ack to client
		write(client_message.sockfd, net_command_buf_ack, net_command_buf_len_ack);

		//reinit inner variable
		net_command_buf_len = 0;
		net_command_buf_len_ack = 0;
		bzero(net_command_buf, NET_COMMAND_BUF_LEN);
		bzero(net_command_buf_ack, NET_COMMAND_BUF_LEN);

		net_command_buf_len = read(client_message.sockfd, net_command_buf, NET_COMMAND_BUF_LEN);
	}

	//close socket
	close(client_message.sockfd);

	//return result
	return(NULL);
}

/****************************************************************
 *This function is pc_command_process_func
 *	(1)process pc send control command function
 ****************************************************************/
static void pc_command_process_func(const unsigned char *arg, unsigned int len, unsigned char *return_arg, unsigned int *return_len)
{
    unsigned char temp_i;
	unsigned int pc_commad;
    unsigned int time_s, time_ms;
    struct  timeval    get_tv, set_tv;
    struct  timezone   get_tz;


    //verity frame
    if((arg[0] == 0xeb) && (arg[1] == 0x90)){
        temp_i = FRAME_CORRECT;
    }

    //verity frame right
    if(temp_i == FRAME_CORRECT)
    {
        //get command
        pc_commad = arg[2];
        pc_commad =( pc_commad << 8 ) | arg[3];

        fprintf(stderr,"rec cmd:%x \n", pc_commad);

        //run pc_commad
        switch(pc_commad){
            case 0x0101:
                //use tl5158
                system("rm -rf /home/root/liangxao/video_test/choose_channel/*");
                system("sync;sync;sync");
                system("touch /home/root/liangxao/video_test/choose_channel/tl5158");
                system("sync;sync;sync");
                sleep(2);
                fprintf(stderr,"use tl5158\n");
                system("reboot");
                break;

            case 0x0202:
                //use tvp800*600
                system("rm -rf /home/root/liangxao/video_test/choose_channel/*");
                system("sync;sync;sync");
                system("touch /home/root/liangxao/video_test/choose_channel/tvp800_600");
                system("sync;sync;sync");
                sleep(2);
                fprintf(stderr,"use tvp800*600\n");
                system("reboot");
                break;

            case 0x0303:
                //use tvp1024*768
                system("rm -rf /home/root/liangxao/video_test/choose_channel/*");
                system("sync;sync;sync");
                system("touch /home/root/liangxao/video_test/choose_channel/tvp1024_768");
                system("sync;sync;sync");
                sleep(2);
                fprintf(stderr,"use tvp1024*768\n");
                system("reboot");
                break;

            case 0x0404:
                //use tvp1280*1024
                system("rm -rf /home/root/liangxao/video_test/choose_channel/*");
                system("sync;sync;sync");
                system("touch /home/root/liangxao/video_test/choose_channel/tvp1280_1024");
                system("sync;sync;sync");
                sleep(2);
                fprintf(stderr,"use tvp1280*1024\n");
                system("reboot");
                break;

            case 0x0505:
                //use tvp1408*1050
                system("rm -rf /home/root/liangxao/video_test/choose_channel/*");
                system("sync;sync;sync");
                system("touch /home/root/liangxao/video_test/choose_channel/tvp1408_1050");
                system("sync;sync;sync");
                sleep(2);
                fprintf(stderr,"use tvp1408*1050\n");
                system("reboot");
                break;

            case 0x0606:

                // get system
                gettimeofday(&get_tv,&get_tz);

                // print time
                printf("tv_sec:%d\n",get_tv.tv_sec);
                printf("tv_usec:%d\n",get_tv.tv_usec);
                printf("tz_minuteswest:%d\n",get_tz.tz_minuteswest);
                printf("tz_dsttime:%d\n",get_tz.tz_dsttime);

                // get second data
                time_s = arg[4];
                time_s <<= 8;
                time_s |= arg[5];
                time_s <<= 8;
                time_s |= arg[6];
                time_s <<= 8;
                time_s |= arg[7];

                // get msecond
                time_ms = arg[8];
                time_ms <<= 8;
                time_ms |= arg[9];

                // fill time data
                set_tv.tv_sec = time_s;
                set_tv.tv_usec = time_ms * 1000;

                printf("set tv_sec:%d\n", set_tv.tv_sec);
                printf("set tv_usec:%d\n", set_tv.tv_usec);

                // config time
                settimeofday(&set_tv,&get_tz);

                // get system
                gettimeofday(&get_tv,&get_tz);

                // print time
                printf("tv_sec:%d\n",get_tv.tv_sec);
                printf("tv_usec:%d\n",get_tv.tv_usec);
                printf("tz_minuteswest:%d\n",get_tz.tz_minuteswest);
                printf("tz_dsttime:%d\n",get_tz.tz_dsttime);

                break;

            default:
                break;
        }
    }

    //test ack
    *return_len = len;
    memcpy(return_arg, arg, *return_len);

#ifdef	TST_CODE_SWITCH
	fprintf(stderr,"send data len:%d\n", *return_len);
#endif
}


